package com.ruoyi.central.controller;

import java.util.*;

import com.ruoyi.central.controller.vo.ProcessStepRunVo;
import com.ruoyi.central.domain.*;
import com.ruoyi.central.enums.MaterialStatusEnum;
import com.ruoyi.central.enums.OperationTypeEnum;
import com.ruoyi.central.service.*;
import com.ruoyi.common.enums.common.TaskStatusEnum;
import com.ruoyi.common.exception.base.service.ServiceException;
import com.ruoyi.common.utils.CollectionUtils;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.bean.EnumUtils;
import com.ruoyi.common.utils.service.ServiceUtils;
import com.ruoyi.common.validation.group.InsertGroup;
import com.ruoyi.common.validation.group.UpdateGroup;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.utils.bean.SelectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.poi.ExcelUtil;
import org.springframework.validation.annotation.Validated;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.validation.group.UpdateBatchGroup;
import com.ruoyi.common.core.domain.StateVo;

/**
 * 执行工序Controller
 * 
 * @author SunLuQuan
 * @date 2022-04-26
 */
@Controller
@RequestMapping("/central/centralProcessStepRun")
public class TopCentralProcessStepRunController extends BaseController
{
    private String prefix = "central/centralProcessStepRun";

    @Autowired
    private ITopCentralProcessStepRunService topCentralProcessStepRunService;
    @Autowired
    private ITopCentralProcessStepService processStepService;
    @Autowired
    private ITopCentralArtProcessRunService artProcessRunService;

    @RequiresPermissions("central:centralProcessStepRun:view")
    @GetMapping()
    public String centralProcessStepRun()
    {
        return prefix + "/centralProcessStepRun";
    }

    @Autowired
    private ITopCentralTaskCmdRunService taskCmdRunService;

    @Autowired
    private ITopCentralOperationStationMaterialService operationStationMaterialService;

    @Autowired
    private ITopCentralMaterialService materialService;

    /**
     * 获取执行工艺编号下的所有执行工序时间线
     * @param artProcessRunId
     * @return
     */
    @GetMapping("/getTimeLineByArtProcessRunId/{artProcessRunId}")
    @ResponseBody
    public AjaxResult getTimeLineByArtProcessRunId(@PathVariable("artProcessRunId") Integer artProcessRunId){

        List<TopCentralProcessStepRun> processStepRuns = topCentralProcessStepRunService.getTimeLineByArtProcessRunId(artProcessRunId);

        if(StringUtils.isNotEmpty(processStepRuns)){
            processStepRuns.forEach(processStepRun -> {
                String processingTime;
                if(EnumUtils.equals(TaskStatusEnum.EXECUTED_FINISH,processStepRun.getTaskStatus())){
                    processingTime = DateUtils.getDatePoor(processStepRun.getCreateTime(),processStepRun.getUpdateTime());
                }else{
                    processingTime = DateUtils.getDatePoor(processStepRun.getCreateTime(),DateUtils.getNowDate());
                }
                processStepRun.setProcessingTime(processingTime);
            });

        }

        return AjaxResult.success(processStepRuns);

    }
    /**
     * 完成工序执行
     *  //1.查询状态不为开始的数据  根据顺序获取前两个
*         //2.判断第一个执行工序对象是否 和 当前工序编号是否一致 ，第一个执行工序对象是否为执行中
*         //3.修改当前执行工序为完成
*         //3.1检测当前执行工序下的执行指令是否全部完成
*         //4.修改下一道执行工序为执行中
*         //4.1创建当前工序的所有执行指令数据
     *         请使用 {@link com.ruoyi.central.service.custom.impl.ManualOperationStationServiceImpl  }  的方法：toCompleteProcess
     * @return
     */
//    @RequiresPermissions("central:centralProcessStepRun:update")
//    @PostMapping("/toCompleteProcess")
//    @ResponseBody
    @Deprecated
    public AjaxResult toCompleteProcess(@RequestBody ProcessStepRunVo processStepRunVo){

        Integer artProcessRunId = processStepRunVo.getArtProcessRunId();

        Integer processStepRunId = processStepRunVo.getProcessStepRunId();
        //当前执行工序的工艺对象
        TopCentralArtProcessRun activeArtProcessRun = null;
        //当前执行工艺下所有的执行工序对象
        List<TopCentralProcessStepRun> processStepRuns = null;
        //当前执行工艺下需要完成的执行工序对象
        TopCentralProcessStepRun activeProcessStepRun = null;
        //当前需要完成的执行工序对象编号
        Integer activeProcessStepRunId = null;
        //当前需要修改的执行工序对象 集合容器
        List<TopCentralProcessStepRun> processStepRunsOfUpdate = null;
        //当前需要修改为完成的执行工序对象
        TopCentralProcessStepRun finishedProcessStepRun = null;
        //当前加工工序的物料
        String materialId = null;
        TopCentralMaterial material = null;

        activeArtProcessRun = artProcessRunService.selectUsableById(artProcessRunId);
        Assert.notNull(activeArtProcessRun,StringUtils.format("当前执行工艺编号：{}不存在或状态为不可用！",artProcessRunId));
        materialId = activeArtProcessRun.getProdId();

        material = materialService.selectById(materialId);
        Assert.notNull(activeArtProcessRun,StringUtils.format("当前物料编号：{}不存在或状态为不可用！",materialId));

        if(!EnumUtils.equals(MaterialStatusEnum.USE_OF_STATUS,material.getMaterialStatus())){
            throw new ServiceException("当前物料编号：{} ， 物料标记状态：'{}' 不能进行操作！",materialId,EnumUtils.toEnum(MaterialStatusEnum.class,material.getMaterialStatus()).getDescription());
        }

        processStepRuns = topCentralProcessStepRunService.selectByArtProcessRunId(artProcessRunId);
        Assert.notEmpty(processStepRuns,StringUtils.format("当前执行工艺编号：{} 未找到绑定的可执行工序对象！",artProcessRunId));

        activeProcessStepRun = CollectionUtils.getFirst(processStepRuns);
        if(!StringUtils.equals(activeProcessStepRun.getId(),processStepRunId)){
            TopCentralProcessStepRun processStepRun = topCentralProcessStepRunService.selectUsableById(processStepRunId);
            Assert.notNull(activeArtProcessRun,StringUtils.format("当前执行工序编号：{}不存在或状态为不可用!",processStepRunId));

            if(!StringUtils.equals(artProcessRunId,processStepRun.getArtProcessRunId())){
                throw new ServiceException("当前执行工序：{} 与当前执行工艺不符！",processStepRun.getId());
            }
            if(processStepRun.getWeight()>activeProcessStepRun.getWeight()){
                throw new ServiceException("当前执行工序：{} 之前还有未执行完成的工序，不能完成！",processStepRun.getId());
            }
            throw new ServiceException("当前执行工序：{} 与实际不符！",processStepRun.getId());
        }
        if(!EnumUtils.equals(TaskStatusEnum.EXECUTING,activeProcessStepRun.getTaskStatus())){
            throw new ServiceException("当前执行工序状态为：{}，不能完成！",EnumUtils.toEnum(TaskStatusEnum.class,activeProcessStepRun.getTaskStatus()));
        }

        activeProcessStepRunId = activeProcessStepRun.getId();

        //TODO 检查是否当前完成的工序下 所有的执行指令都完成了
        //如果当前需要修改为完成的工序 下面还有未执行完成的执行任务指令  抛出异常
        if(!taskCmdRunService.isTaskCmdRunFinishedByProcessStepRunId(activeProcessStepRunId)){
            throw new ServiceException("当前执行工序：{} ，还有未执行完成的执行任务指令，请先完成当前工序下所有的执行任务指令，再完成当前执行工序！",activeProcessStepRun.getName());
        }

        activeProcessStepRun.setTaskStatus(TaskStatusEnum.EXECUTED_FINISH.getValue());
        processStepRunsOfUpdate = new ArrayList<>();


        finishedProcessStepRun = new TopCentralProcessStepRun();
        finishedProcessStepRun.setId(activeProcessStepRunId);
        finishedProcessStepRun.setTaskStatus(activeProcessStepRun.getTaskStatus());

        processStepRunsOfUpdate.add(finishedProcessStepRun);

        if(processStepRuns.size()>1){
            //修改下一道工序为执行
            TopCentralProcessStepRun nextProcessStepRun = processStepRuns.get(1);
            Integer nextProcessStepRunId = nextProcessStepRun.getId();
            nextProcessStepRun.setTaskStatus(TaskStatusEnum.EXECUTING.getValue());
            TopCentralProcessStepRun activeProcessStepRunOfUpdate = new TopCentralProcessStepRun();
            activeProcessStepRunOfUpdate.setId(nextProcessStepRunId);
            activeProcessStepRunOfUpdate.setTaskStatus(nextProcessStepRun.getTaskStatus());

            processStepRunsOfUpdate.add(activeProcessStepRunOfUpdate);


            //TODO 生成当前工序下所有的执行指令 并将第一个设置为执行中
            List<TopCentralTaskCmdRun> taskCmdRuns = taskCmdRunService.selectByProcessStepRunId(nextProcessStepRunId);
            if(StringUtils.isNotEmpty(taskCmdRuns)){
                if(taskCmdRuns.size()>1){
                    taskCmdRuns.sort(Comparator.comparing(TopCentralTaskCmdRun::getWeight));
                }
                TopCentralTaskCmdRun taskCmdRunOfFirst = CollectionUtils.getFirst(taskCmdRuns);

                TopCentralTaskCmd taskCmd = taskCmdRunOfFirst.getTaskCmd();
                Assert.notNull(taskCmd,"未找到任务执行指令！");
                if(EnumUtils.equals(OperationTypeEnum.MANUAL_TYPE,taskCmd.getCommandType())){
                    TopCentralTaskCmdRun taskCmdRunOfActive =
                            BeanUtils.initialize(TopCentralTaskCmdRun.class,(taskCmdRun -> {
                                taskCmdRun.setId(taskCmdRunOfFirst.getId());
                                taskCmdRun.setTaskStatus(TaskStatusEnum.NOT_START.getValue());
                            }));
                    taskCmdRunService.updateById(taskCmdRunOfActive);
                }
            }
        }else{//如果只有一条数据 说明当前执行工序是最后一道执行工序 //需要进行特殊操作
            //如果是最后一道工序 修改当前执行工艺为完成

            //操作工位-物料 绑定表的行数据编号
            Integer operationStationMaterialId = null;
            //操作工位-物料对象 （当前工序为当前工艺的最后一条完成工序后 需要将绑定数据删除）
            TopCentralOperationStationMaterial operationStationMaterial = null;

            TopCentralArtProcessRun updateArtProcessRunForComplete = new TopCentralArtProcessRun();
            updateArtProcessRunForComplete.setId(artProcessRunId);
            updateArtProcessRunForComplete.setTaskStatus(TaskStatusEnum.EXECUTED_FINISH);

            topCentralProcessStepRunService.updateById(finishedProcessStepRun);
            //TODO 需要将当前物料与操作台 解绑
            operationStationMaterial = operationStationMaterialService.selectByMaterialId(activeArtProcessRun.getProdId());

            Assert.notNull(operationStationMaterial,"物料编号："+materialId+" ,绑定的操作工位丢失！");

            operationStationMaterialId = operationStationMaterial.getId();

            operationStationMaterialService.deleteById(operationStationMaterialId);

            //TODO 需要修改物料表的状态
            TopCentralMaterial materialOfUpdate = new TopCentralMaterial();
            materialOfUpdate.setId(materialId);
            materialOfUpdate.setMaterialStatus(MaterialStatusEnum.FINISHED_OF_STATUS.getValue());

            materialService.updateById(materialOfUpdate);

        }
        if(processStepRunsOfUpdate.size()==1){
            topCentralProcessStepRunService.updateById(CollectionUtils.getFirst(processStepRunsOfUpdate));
        }else{
            topCentralProcessStepRunService.updateBatchById(processStepRunsOfUpdate);
        }

        return AjaxResult.success(processStepRuns);
    }

    /**
     * 查询执行工序列表
     */
    @RequiresPermissions("central:centralProcessStepRun:list")
    @GetMapping("/list")
    @ResponseBody
    public TableDataInfo list(TopCentralProcessStepRun topCentralProcessStepRun)
    {
        startPage();
        List<TopCentralProcessStepRun> list = topCentralProcessStepRunService.selectList(topCentralProcessStepRun);
        ServiceUtils.complete(list,artProcessRunService,(artProcessRunMap,processStepRun)->{
            if(artProcessRunMap.containsKey(processStepRun.getArtProcessRunId())){
                processStepRun.setArtProcessRun(artProcessRunMap.get(processStepRun.getArtProcessRunId()));
            }
        });
        return getDataTable(list);
    }

    /**
     * 查询简单的执行工序列表 用于select选择器
     */
    @GetMapping("/simpleList")
    @ResponseBody
    public AjaxResult simpleList(TopCentralProcessStepRun topCentralProcessStepRun){

        Collection<TopCentralProcessStepRun> topCentralProcessStepRunList = topCentralProcessStepRunService.selectAllMap().values();

        return AjaxResult.success(SelectUtils.buildSelectList(topCentralProcessStepRunList,TopCentralProcessStepRun::getId,TopCentralProcessStepRun::getName));
    }

    /**
     * 获取执行工序详细信息
     */
    @RequiresPermissions("central:centralProcessStepRun:query")
    @GetMapping(value = "/{id}")
    @ResponseBody
    public AjaxResult getInfo(@PathVariable("id") Integer id)
    {
        return AjaxResult.success(topCentralProcessStepRunService.selectById(id));
    }

    /**
     * 获取自增排序值
     * @param topCentralProcessStepRun 过滤条件
     * @return
     */
    @GetMapping("/getIncrementWeight")
    @ResponseBody
    public AjaxResult getIncrementWeight(TopCentralProcessStepRun topCentralProcessStepRun){
        int weigth = topCentralProcessStepRunService.getMaxOfWeight(topCentralProcessStepRun);
        return AjaxResult.success(++weigth);
    }

    /**
     * 下载执行工序导入模板
     */
    @GetMapping("/importTemplate")
    @ResponseBody
    public void importTemplate(HttpServletResponse response)
    {
        ExcelUtil<TopCentralProcessStepRun> util = new ExcelUtil<>(TopCentralProcessStepRun.class);
        util.importTemplateExcel(response, "执行工序数据");
    }

    /**
     * 导入执行工序数据
     * @param file 执行工序数据文件
     * @param updateSupport 是否为更新
     */
    @Log(title = "执行工序", businessType = BusinessType.IMPORT)
    @RequiresPermissions("central:centralProcessStepRun:import")
    @PostMapping("/importData")
    @ResponseBody
    public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
    {
        ExcelUtil<TopCentralProcessStepRun> util = new ExcelUtil<>(TopCentralProcessStepRun.class);
        List<TopCentralProcessStepRun> topCentralProcessStepRunList = util.importExcel(file.getInputStream());

        if(updateSupport){
            if(topCentralProcessStepRunService.updateBatchById(topCentralProcessStepRunList)){
                return AjaxResult.success("导入执行工序数据覆盖成功！");
            }
            return AjaxResult.error("导入执行工序数据覆盖失败！");
        }
        if(topCentralProcessStepRunService.insertBatch(topCentralProcessStepRunList)){
            return AjaxResult.success("导入执行工序数据新增成功！");
        }
        return AjaxResult.error("导入执行工序数据新增失败！");
    }

    /**
     * 导出执行工序列表
     */
    @RequiresPermissions("central:centralProcessStepRun:export")
    @Log(title = "执行工序", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(TopCentralProcessStepRun topCentralProcessStepRun)
    {
        List<TopCentralProcessStepRun> list = topCentralProcessStepRunService.selectList(topCentralProcessStepRun);
        ExcelUtil<TopCentralProcessStepRun> util = new ExcelUtil<TopCentralProcessStepRun>(TopCentralProcessStepRun.class);
        return util.exportExcel(list, "执行工序数据");
    }

    /**
     * 新增执行工序
     */
    @GetMapping("/add")
    public String add()
    {
        return prefix + "/add";
    }

    /**
     * 新增保存执行工序
     */
    @RequiresPermissions("central:centralProcessStepRun:add")
    @Log(title = "执行工序", businessType = BusinessType.INSERT)
    @PostMapping
    @ResponseBody
    public AjaxResult addSave(@Validated(InsertGroup.class) @RequestBody TopCentralProcessStepRun topCentralProcessStepRun)
    {
        return toAjax(topCentralProcessStepRunService.insert(topCentralProcessStepRun));
    }

    /**
     * 修改执行工序
     */
    @RequiresPermissions("central:centralProcessStepRun:edit")
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Integer id, ModelMap mmap)
    {
        TopCentralProcessStepRun topCentralProcessStepRun = topCentralProcessStepRunService.selectById(id);
        mmap.put("topCentralProcessStepRun", topCentralProcessStepRun);
        return prefix + "/edit";
    }

    /**
     * 修改保存执行工序
     */
    @RequiresPermissions("central:centralProcessStepRun:edit")
    @Log(title = "执行工序", businessType = BusinessType.UPDATE)
    @PutMapping
    @ResponseBody
    public AjaxResult editSave(@Validated(UpdateGroup.class) @RequestBody TopCentralProcessStepRun topCentralProcessStepRun)
    {
        return toAjax(topCentralProcessStepRunService.updateById(topCentralProcessStepRun));
    }

    /**
     * 修改执行工序 状态 根据 ids 主键
     */
    @RequiresPermissions("central:centralProcessStepRun:edit")
    @Log(title = "执行工序", businessType = BusinessType.UPDATE)
    @PutMapping("/updateStateByIds")
    @ResponseBody
    public AjaxResult updateStateByIds(@Validated(value= UpdateBatchGroup.class)@RequestBody StateVo<Integer> stateVo)
    {
        return toAjax(topCentralProcessStepRunService.updateStateByIds(stateVo.getIds(),stateVo.getState()));
    }

    /**
     * 删除执行工序
     */
    @RequiresPermissions("central:centralProcessStepRun:remove")
    @Log(title = "执行工序", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    @ResponseBody
    public AjaxResult deleteByIds(@PathVariable("ids") List<Integer> ids)
    {
            return toAjax(topCentralProcessStepRunService.deleteByIds(ids));
    }
}
